#include <algorithm>
#include <cstdio>
#include <cstring>
#include <map>
#include <queue>

const int N = 5001;
int n, m, s, t, e_cnt = 1, ans = 0, cost = 0;
int heads[N], pre[N], dis[N], f[N], last[N];
bool vis[N];

struct Edge {
  int v, nxt, flow, c;
} e[100002];

inline void add(int u, int v, int f, int cos) {
  e[++e_cnt].flow = f, e[e_cnt].nxt = heads[u], e[e_cnt].c = cos, e[e_cnt].v = v,
  heads[u] = e_cnt;
  e[++e_cnt].flow = 0, e[e_cnt].nxt = heads[v], e[e_cnt].v = u, e[e_cnt].c = -cos,
  heads[v] = e_cnt;
}

inline bool spfa() {
  std::queue<int> q;
  memset(dis, -0x3f, sizeof(dis));
  memset(vis, 0, sizeof(vis));
  memset(f, 0x3f, sizeof(f));
  q.push(s);
  vis[s] = true, dis[s] = 0, pre[t] = -1;
  while (!q.empty()) {
    int x = q.front();
    q.pop();
    vis[x] = false;
    for (int i = heads[x]; i; i = e[i].nxt) {
      if (e[i].flow > 0 && dis[e[i].v] < dis[x] + e[i].c) {
        dis[e[i].v] = dis[x] + e[i].c;
        pre[e[i].v] = x;
        last[e[i].v] = i;
        f[e[i].v] = std::min(f[x], e[i].flow);
        if (!vis[e[i].v]) {
          q.push(e[i].v);
          vis[e[i].v] = true;
        }
      }
    }
  }
  return pre[t] != -1;
}

inline void MCMF() {
  while (spfa()) {
    int cur = t;
    ans += f[t];
    cost += f[t] * dis[t];
    while (cur != s) {
      e[last[cur]].flow -= f[t];
      e[last[cur] ^ 1].flow += f[t];
      cur = pre[cur];
    }
  }
}

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen("testdata.in", "r", stdin);
  freopen("testdata.out", "w", stdout);
#endif
#ifndef LOCAL
  freopen("MCMF.in", "r", stdin);
  freopen("MCMF.out", "w", stdout);
#endif
#endif
  scanf("%d", &n);
  for (int i = 1, w, h; i <= n; ++i) {
    scanf("%d%d", &w, &h);
    if ()
  }
  MCMF();
  printf("%d %d", ans, cost);
  return 0;
}